package cn.lk.netty.rpc.configure;

import cn.lk.netty.rpc.bean.Request;
import cn.lk.netty.rpc.bean.Response;
import cn.lk.netty.rpc.netty.NettyClient;
import cn.lk.netty.rpc.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;

/**
 * @ClassName RpcFactory
 * @Deseription TODO
 * @Author hu'nan
 * @Date 2020/4/5 13:38
 * @Version 1.0
 **/
@Component
public class RpcFactory<T> implements InvocationHandler {

    @Autowired
    NettyClient client;

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        Request request = new Request();
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameters(objects);
        request.setParameterTypes(method.getParameterTypes());
        request.setId(IdUtil.getId());

        Object result = client.send(request);
        Class<?> returnType = method.getReturnType();

        Response response = JSON.parseObject(result.toString(), Response.class);
        if (response.getCode() == 1) throw new Exception(response.getError_msg());
        Object data = response.getData();
        if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)) return data;
        else if (Collection.class.isAssignableFrom(returnType)) return JSONArray.parseArray(data.toString(), Object.class);
        else if (Map.class.isAssignableFrom(returnType)) return JSON.parseObject(data.toString(), Map.class);
        else return JSONObject.parseObject(data.toString(), returnType);
    }
}
